package com.thenie.chat.controller;

import cn.hutool.json.JSONUtil;
import com.thenie.chat.pojo.User;
import com.thenie.chat.util.WebSocketUtil;
import com.thenie.chat.vo.DialogWorldMessage;
import com.thenie.chat.vo.RespBean;
import com.thenie.chat.vo.RespBeanEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description 好友聊天处理器（/ws/dialog?userId=）
 * @Author thenie
 * @Data 2022/5/28 18:26
 */
@Component
@Slf4j
public class DialogWorldSocketHandler extends AbstractWebSocketHandler {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;


    public static final Map<String, WebSocketSession> WORLD_SESSION_MAP = new ConcurrentHashMap<>(32);


    /**
     * 连接成功后调用
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userId = WebSocketUtil.getUserId(session);
        User currentUser = WebSocketUtil.getCurrentUser(session);
        //信息添加到缓存
        redisTemplate.opsForValue().set("worldUser:"+userId,currentUser);
        //保存本地session
        WORLD_SESSION_MAP.put(userId, session);

        //设置进入聊天室广播消息
        TextMessage msg = new TextMessage(JSONUtil.toJsonStr(
                RespBean.success(RespBeanEnum.SEND_ONLINE_UP_MESSAGE,
                        new DialogWorldMessage("进入聊天室",currentUser)
                )
        ));
        //广播
        for (Map.Entry<String, WebSocketSession> entry : WORLD_SESSION_MAP.entrySet()) {
            if (entry.getKey().equals(userId)){
                continue;
            }
            entry.getValue().sendMessage(msg);
        }

    }


    /**
     * 转发消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message)  {

        try {
            //获取消息
            String text = message.getPayload();
            User currentUser = WebSocketUtil.getCurrentUser(session);

            //设置消息
            TextMessage msg = new TextMessage(JSONUtil.toJsonStr(
                    RespBean.success(RespBeanEnum.SEND_ONE_MESSAGE,
                            new DialogWorldMessage(text, currentUser)
                    )
            ));
            //广播消息发送
            for (Map.Entry<String, WebSocketSession> entry : WORLD_SESSION_MAP.entrySet()) {
                if (entry.getKey().equals(currentUser.getId().toString())) {
                    continue;
                }
                entry.getValue().sendMessage(msg);

            }
        } catch (IOException e) {
            log.warn("DialogWorldSocketHandler.handleTextMessage",e);
        }

    }


    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
    }

    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) {
    }

    /**
     * WS 连接出错时调用
     *
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        log.error("webSocket连接出错", exception);
    }

    /**
     * 连接关闭后调用
     *
     * @param session
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        //通知下线
        String userId = WebSocketUtil.getUserId(session);
        Long id = Long.valueOf(userId);

        //删除缓存
        redisTemplate.delete("worldUser:"+userId);

        //删除本地session
        WORLD_SESSION_MAP.remove(userId);

        for (Map.Entry<String, WebSocketSession> entry : WORLD_SESSION_MAP.entrySet()) {
            WebSocketUtil.sendOnlineDownMsg(entry.getValue(),id);
        }
    }

    /**
     * 是否支持分片消息
     *
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}
